package com.xcx.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 利用jackson的json工具类
 *
 * @author yangjun
 * @date 2018年7月14日 下午10:43:04
 */
@Slf4j
public class JsonUtils {


    /**
     * Map  TypeReference
     **/
    public static final TypeReference<Map<String, String>> TYPE_REFERENCE = new TypeReference<Map<String, String>>() {
    };

    private static ObjectMapper objectMapper = JsonObjectMapperFactory.getInstance();

    /**
     * 将对象转换为JSON字符串
     *
     * @param obj
     * @return
     */
    public static String toJson(final Object obj) {
        try {
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("json序列化异常", e);
            throw new IllegalArgumentException("转换为JSON字符串时异常", e);
        }
    }

    /**
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <K, V> Map<K, V> toMap(String value) {
        return parse(value, new HashMap<K, V>().getClass());
    }

    /**
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <V> List<V> toList(String value) {
        return parse(value, new ArrayList<V>().getClass());
    }


    /**
     * 将对象转换为JSON字符串
     *
     * @param obj
     * @return
     */
    public static void toOutputStream(final OutputStream out, final Object obj) {
        try {
            objectMapper.writeValue(out, obj);
            ;
        } catch (Exception e) {
            log.error("json序列化异常", e);
            throw new IllegalArgumentException("转换为JSON字符串时异常", e);
        }
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param json
     * @param clazz
     * @return
     */
    public static <T> T parse(final String json, final Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * json 转 List<T>
     */
    public static <T> List<T> jsonToList(String jsonString, Class<T> clazz) {
        @SuppressWarnings("unchecked")
        List<T> ts = (List<T>) JSONArray.parseArray(jsonString, clazz);
        return ts;
    }


    /**
     * 将JSON字符串转换为Map
     *
     * @param json
     * @return
     */
    public static Map<String, String> parse(final String json) {
        try {
            return objectMapper.readValue(json, TYPE_REFERENCE);
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param in
     * @param clazz
     * @return
     */
    public static <T> T parse(final InputStream in, final Class<T> clazz) {
        try {
            return objectMapper.readValue(in, clazz);
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param json
     * @param valueTypeRef
     * @return
     */
    public static <T> T parse(final String json, final TypeReference<T> valueTypeRef) {
        try {
            return objectMapper.readValue(json, valueTypeRef);
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param json
     * @param javaType
     * @return
     */
    public static <T> T parse(final String json, final JavaType javaType) {
        try {
            return objectMapper.readValue(json, javaType);
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param json
     * @param parametrized
     * @param parameterClazzes
     * @return
     */
    public static <T> T parse(final String json, final Class<?> parametrized, final Class<?>... parameterClazzes) {
        try {
            return parse(json, objectMapper.getTypeFactory().constructParametricType(parametrized, parameterClazzes));
        } catch (Exception e) {
            log.error("json反序列化异常", e);
            throw new IllegalArgumentException("由JSON字符串时转换为对象时异常", e);
        }
    }

    /**
     * <P>json对象映射工厂<P>
     */
    public static class JsonObjectMapperFactory {
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        private static ObjectMapper om = new ObjectMapper();

        static {
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            om.setDateFormat(new SimpleDateFormat(DATE_FORMAT));
            om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        }

        public static ObjectMapper getInstance() {
            return om;
        }
    }
}
